//
// Created by Crazy.Mo on 2018/9/6.
//
#include <jni.h>
#include <pthread.h>
#include <unistd.h>
#include <string>
#include <android/log.h>

#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,"NativeThread",__VA_ARGS__);

extern JavaVM *_vm;//使用全局变量

/**
 * 因为需要回调Java层的方法，而在C/C++层回调Java方法需要一个对应的Java Class字节码对象，所以需要传递过来
 */
struct JavaContext {
    jobject instance;
};

void *interactWithJava(void *args) {
    JNIEnv *env = 0;
    LOGE("【通过JavaVM传入env执行AttachCurrentThread把env 附加到虚拟机，附加成功之后env就被赋值了】");
    //等价于_vm不等于NULL
    if (_vm) {
        jint ret = _vm->AttachCurrentThread(&env, 0); // native线程附加到Java 虚拟机,附加成功之后env就被赋值了
        if (ret == JNI_OK) {
            LOGE("【AttachCurrentThread 成功，env赋值】");
            JavaContext *context = static_cast<JavaContext *>(args);
            //等价于 context!=NULL
            if (context) {
               // sleep(2);//模拟下载耗时2S
                //获得MainActivity的class对象
                jclass clz = env->GetObjectClass(context->instance);
                LOGE("thread: clz1:%d",clz!=0);
                //com.crazymo.ndk.MainActivity
                ///为什么找不到？因为线程里attach的jnienv findclass用的bootclassloader只能找到系统的类，不能找到自己编写的类
                jclass clz2 = env->FindClass("com/crazymo/ndk/jni/Blog");
                if (clz) {
                    // 反射获得方法
                    jmethodID updui_method = env->GetMethodID(clz, "update", "()V");
                    if (updui_method) {
                        LOGE("【通过反射找到要回调的Java方法的methodID并调用】");
                        env->CallVoidMethod(context->instance, updui_method);
                        env->DeleteGlobalRef(context->instance);
                        delete (context);
                        context = 0;
                    }
                }
                LOGE("current thread:%ld",pthread_self())

            }
        }
    } else {
        LOGE("context==NULL");
    }
    //分离
    _vm->DetachCurrentThread();
    return 0;//线程函数必须记得返回0
}

//定义指向函数的指针
void *pthreadTask(void *args) {
    int *num = static_cast<int *>(args);
    LOGE("在Native线程中执行num=%d", *num);
    return 0;
}

extern "C"
JNIEXPORT void JNICALL
Java_com_crazymo_ndk_jni_JNIHelper_createNativeThread(JNIEnv *env, jobject instance) {
    pthread_t pid;
    int num = 2008;
    pthread_create(&pid, 0, pthreadTask, &num);//创建并启动Native线程
}

extern "C"
JNIEXPORT void JNICALL
Java_com_crazymo_ndk_jni_JNIHelper_runNativeCallJava(JNIEnv *env, jobject instance, jobject obj) {
    //注意这里的instance 代表的是runNativeCallJava所属类的实例
    LOGE("在C/C++ 层创建Native线程...")
    jclass clz= env->FindClass("com/crazymo/ndk/MainActivity");
    LOGE("clz:====%d",clz != 0)
    pthread_t pid;
    //必须把传递过来的对象保存为全局引用，然后才能传递到另一个线程使用，否则报attempt to use stale WeakGlobal 0x3 (should be 0x7)
    JavaContext *context = new JavaContext;
    context->instance = env->NewGlobalRef(obj);
    pthread_create(&pid, 0, interactWithJava, context);//创建并启动Native线程
}
